home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 49 / Amiga Format CD49 (2000-01-17)(Future Publishing)(GB)(Track 1 of 3)[!][issue 2000-02].iso / -serious- / misc / db3.6-beta / db3.6-beta-src / select.c < prev    next >
C/C++ Source or Header  |  1999-11-30  |  25KB  |  793 lines

  1. #include <exec/types.h>
  2. #include <exec/memory.h>
  3. #include <exec/nodes.h>
  4. #include <exec/lists.h>
  5. #include <intuition/intuition.h>
  6. #include <intuition/classes.h>
  7. #include <intuition/classusr.h>
  8. #include <intuition/imageclass.h>
  9. #include <intuition/gadgetclass.h>
  10. #include <libraries/gadtools.h>
  11. #include <libraries/commodities.h> /* This has a nice qualifier #define */
  12. #include <graphics/displayinfo.h>
  13. #include <graphics/gfxbase.h>
  14.  
  15. #include <proto/exec.h>
  16. #include <proto/intuition.h>
  17. #include <proto/gadtools.h>
  18. #include <proto/graphics.h>
  19. #include <proto/utility.h>
  20. #include <proto/dos.h>  /* Delay() for debugging */
  21.  
  22. #include <string.h>
  23. #include <stdlib.h>     /* malloc & free */
  24. #include <stdio.h>      /* debugging */
  25.  
  26. #include "db.h"
  27. #include "Select_P.h"
  28. #include "dbparser.h"
  29. #include "dbGUI.h"      /* We use db's font instead of the screen font */
  30.  
  31. #define MARGIN 4
  32. #define TOGGLE_LED *(UBYTE *)0xbfe001 ^= 2
  33.  
  34. extern struct Pro *CurrentPro;
  35.  
  36. /* We use db's font engine instead.
  37. static struct TextAttr       *Font, Attr;
  38. static UWORD                  FontX, FontY;
  39. */
  40.  
  41.  
  42. /*
  43. void FlashLed(void)
  44. {
  45.         int i;
  46.         for (i=0; i<20; i++) {
  47.                 TOGGLE_LED;
  48.                 Delay(10);
  49.         }
  50. }
  51. */
  52.  
  53. /**********************************************************************/
  54. /*                         Support functions                          */
  55. /**********************************************************************/
  56.  
  57.  
  58. static UWORD ComputeX( UWORD value )
  59. {
  60.         return(( UWORD )((( FontX * value ) + 4 ) / 8 ));
  61. }
  62.  
  63. static UWORD ComputeY( UWORD value )
  64. {
  65.         return(( UWORD )((( FontY * value ) + 6 ) / 13 ));
  66. }
  67. /*
  68. static void ComputeFont( UWORD width, UWORD height )
  69. {
  70.         static UWORD                  OffX, OffY;
  71.         Font = &Attr;
  72.         Font->ta_Name = (STRPTR)Scr->RastPort.Font->tf_Message.mn_Node.ln_Name;
  73.         Font->ta_YSize = FontY = Scr->RastPort.Font->tf_YSize;
  74.         FontX = Scr->RastPort.Font->tf_XSize;
  75.  
  76.         OffX = Scr->WBorLeft;
  77.         OffY = Scr->RastPort.TxHeight + Scr->WBorTop + 1;
  78.  
  79.         if ( width && height ) {
  80.                 if (( ComputeX( width ) + OffX + Scr->WBorRight ) > Scr->Width )
  81.                         goto UseTopaz;
  82.                 if (( ComputeY( height ) + OffY + Scr->WBorBottom ) > Scr->Height )
  83.                         goto UseTopaz;
  84.         }
  85.         return;
  86.  
  87. UseTopaz:
  88.         Font->ta_Name = (STRPTR)"topaz.font";
  89.         FontX = FontY = Font->ta_YSize = 8;
  90. }
  91. */
  92.  
  93.  
  94. static void MyCreateAllGadgets(Select *s)
  95. {
  96.         struct Gadget   *g;
  97.         static struct NewGadget ng[] =
  98.                {
  99.                4,   4,  213, 229, NULL       , NULL, GD_SELLview, 0, NULL, (APTR)SELLviewClicked,
  100.                4, 232,  213, 229, (char *)"+", NULL, GD_SELLadd , 0, NULL, (APTR)SELLaddClicked,
  101.                4,   4,  213, 229, (char *)"-", NULL, GD_SELLdel , 0, NULL, (APTR)SELLdelClicked
  102.                };
  103.  
  104.         g = CreateContext( &s->SelGList );
  105.  
  106.  
  107.         // listview
  108.  
  109.         ng[0].ng_VisualInfo = VisualInfo;
  110.         ng[0].ng_TextAttr   = Font;
  111.         ng[0].ng_LeftEdge   = s->SelWnd->BorderLeft + MARGIN;
  112.         ng[0].ng_TopEdge    = s->SelWnd->BorderTop + MARGIN;
  113.         ng[0].ng_Width      = s->SelWnd->Width - s->SelWnd->BorderLeft - s->SelWnd->BorderRight - 2*MARGIN;
  114.         ng[0].ng_Height     = (s->SelWnd->Height - s->SelWnd->BorderTop - s->SelWnd->BorderBottom - 2*MARGIN) - (2*MARGIN + FontY);
  115.  
  116.  
  117.         // button +
  118.  
  119.         ng[1].ng_VisualInfo = VisualInfo;
  120.         ng[1].ng_TextAttr   = Font;
  121.         ng[1].ng_LeftEdge   = s->SelWnd->BorderLeft + MARGIN;
  122.         ng[1].ng_TopEdge    = s->SelWnd->BorderTop + ng[0].ng_Height + 2*MARGIN;
  123.         ng[1].ng_Width      = (s->SelWnd->Width/2) - 2*MARGIN;
  124.         ng[1].ng_Height     = FontY +4;
  125.  
  126.         // button -
  127.  
  128.         ng[2].ng_VisualInfo = VisualInfo;
  129.         ng[2].ng_TextAttr   = Font;
  130.         ng[2].ng_LeftEdge   = s->SelWnd->BorderLeft + ng[1].ng_Width + MARGIN + 1;
  131.         ng[2].ng_TopEdge    = ng[1].ng_TopEdge;
  132.         ng[2].ng_Width      = ng[1].ng_Width;
  133.         ng[2].ng_Height     = ng[1].ng_Height;
  134.  
  135.  
  136.         s->ListView = g = CreateGadget(LISTVIEW_KIND, g, &ng[0],
  137.                 GTLV_Labels, &s->SelList,
  138.                 GTLV_ShowSelected, NULL,
  139.                 GTLV_Selected, s->SelIndex,
  140.                 GTLV_MakeVisible, s->SelIndex,
  141.                 TAG_DONE);
  142.  
  143.         g = CreateGadget(BUTTON_KIND, g, &ng[1],
  144.                 GT_Underscore, '_',
  145.                 TAG_DONE);
  146.  
  147.         g = CreateGadget(BUTTON_KIND, g, &ng[2],
  148.                 GT_Underscore, '_',
  149.                 TAG_DONE);
  150.  
  151.  
  152.         AddGList(s->SelWnd, s->SelGList, -1, -1, NULL);
  153.         RefreshWindowFrame(s->SelWnd);
  154.         RefreshGList(s->SelGList, s->SelWnd, NULL, -1);
  155.         GT_RefreshWindow( s->SelWnd, NULL ); /* Must also be called */
  156. }
  157.  
  158.  
  159.  
  160.  
  161. static void UpdateListView(Select *s)
  162. {
  163.         if (GadToolsBase->lib_Version < 39) {
  164.                 GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL,
  165.                 GTLV_Selected, s->SelIndex,
  166.                 GTLV_Top, s->SelIndex,
  167.                 TAG_END);
  168.         }
  169.         else {
  170.                 GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL,
  171.                 GTLV_Selected, s->SelIndex,
  172.                 GTLV_MakeVisible, s->SelIndex,
  173.                 TAG_END);
  174.         }
  175. }
  176.  
  177. static struct Node *FindIndex(struct List *list, int idx)
  178. {
  179.         /* Returns the node with index idx in the list, (first node is 0) */
  180.         struct Node *cn;        /* Current Node */
  181.         for (cn = list->lh_Head; idx; cn = cn->ln_Succ, idx--);
  182.         return cn;
  183. }
  184.  
  185. static int IndexInList(struct List *list, char *str)
  186. {
  187.         /* returs -1 if str doesn't match somewhere in list */
  188.         int len = strlen(str);
  189.         struct Node *node;
  190.         int i;
  191.         for (node = list->lh_Head, i=0;
  192.                 node->ln_Succ && Strnicmp(str, node->ln_Name, len);
  193.                 node = node->ln_Succ, i++);
  194.         if (node->ln_Succ) return i;
  195.         return -1;
  196. }
  197.  
  198. static int NextMatch(struct Node *cnode, char *str)
  199. {
  200.         /* returs -1 if str doesn't match somewhere in list */
  201.         int len = strlen(str);
  202.         struct Node *node;
  203.         int i;
  204.         if (!cnode->ln_Succ) return -1;
  205.         for (node = cnode->ln_Succ, i=1;
  206.                 node->ln_Succ && Strnicmp(str, node->ln_Name, len);
  207.                 node = node->ln_Succ, i++);
  208.         if (node->ln_Succ) return i;
  209.         return -1;
  210. }
  211.  
  212. static int PrevMatch(struct Node *cnode, char *str)
  213. {
  214.         /* returs -1 if str doesn't match somewhere in list */
  215.         int len = strlen(str);
  216.         struct Node *node;
  217.         int i;
  218.         if (!cnode->ln_Pred) return -1;
  219.         for (node = cnode->ln_Pred, i=1;
  220.                 node->ln_Pred && Strnicmp(str, node->ln_Name, len);
  221.                 node = node->ln_Pred, i++);
  222.         if (node->ln_Pred) return i;
  223.         return -1;
  224. }
  225.  
  226.  
  227. /**********************************************************************/
  228. /*                           Event handlers                           */
  229. /**********************************************************************/
  230.  
  231.  
  232. static int SelNewSize(Select *s)
  233. {
  234.         /* routine for "IDCMP_NEWSIZE". */
  235.  
  236.         RemoveGList(s->SelWnd, s->SelGList, -1);
  237.         FreeGadgets(s->SelGList);
  238.  
  239.         EraseRect(s->SelWnd->RPort, s->SelWnd->BorderLeft, s->SelWnd->BorderTop,
  240.              s->SelWnd->Width - s->SelWnd->BorderRight, s->SelWnd->Height - s->SelWnd->BorderBottom);
  241.  
  242.         MyCreateAllGadgets(s);
  243.  
  244.         return SEL_PRIVATE;
  245. }
  246.  
  247. static int SELOkClicked(Select *s)
  248. {
  249.         /* routine when gadget "_Ok" is clicked. */
  250.         /* CloseSelect(s); */
  251.         return SEL_OK;
  252. }
  253.  
  254. static int SELLaddClicked(Select *s)
  255. {
  256. struct FldInfo *f, *last = NULL;
  257.  
  258.  
  259.         // lets create the new one...
  260.  
  261.         if(!(f = NewFldInfo()))
  262.            {
  263.            DisplayBeep(0);
  264.            return MEM_ERR;
  265.            }
  266.         strcpy(f->Name, "New");
  267.  
  268.         // let's find the last one
  269.         // and attach the new to the list
  270.  
  271.         if(CurrentPro->FirstFldInfo)
  272.           {
  273.           char tmp[5];
  274.           int Count=1;
  275.  
  276.           for(last = CurrentPro->FirstFldInfo; last->Next; last = last->Next,Count++);
  277.  
  278.           sprintf(tmp, "_%ld", Count);
  279.  
  280.           strcat(f->Name, tmp);
  281.           last->Next = f;
  282.           }
  283.         else
  284.           CurrentPro->FirstFldInfo = f;
  285.  
  286.         AddStringLast(s, f->Name);
  287.  
  288.         return(SEL_PRIVATE);
  289. }
  290.  
  291. static int SELLdelClicked(Select *s)
  292. {
  293.  
  294.         DoASCIIParsing();
  295.     return(SEL_PRIVATE);
  296. }
  297.  
  298.  
  299.  
  300. static int SELLviewClicked(Select *s)
  301. {
  302.         /* routine when listview gadget is clicked. */
  303.  
  304.         /* Handle doubleclicks.. */
  305.         if (DoubleClick(s->StartSecs, s->StartMicros, s->SelMsg.Seconds, s->SelMsg.Micros)
  306.                  && s->SelMsg.Code == s->SelIndex) {
  307.                 s->StartSecs = s->StartMicros = 0;      /* Prevent "triple clicks" */
  308.                 s->SelIndex = s->SelMsg.Code;
  309.                 return SELOkClicked(s);
  310.         }
  311.         else {
  312.                 s->StartSecs = s->SelMsg.Seconds;
  313.                 s->StartMicros = s->SelMsg.Micros;
  314.                 s->SelIndex = s->SelMsg.Code;
  315.         }
  316.         return SEL_SELECT;
  317. }
  318.  
  319. static int SelCloseWindow(Select *s)
  320. {
  321.         /* routine for "IDCMP_CLOSEWINDOW". */
  322.         CloseSelect(s);
  323.         return SEL_CANCEL;
  324. }
  325.  
  326. static int SELCancelClicked(Select *s)
  327. {
  328.         /* routine when gadget "_Cancel" is clicked. */
  329.         return SelCloseWindow(s);
  330. }
  331.  
  332.  
  333. static int SelVanillaKey(Select *s)
  334. {
  335.         /* routine for "IDCMP_VANILLAKEY". */
  336.         int len;
  337.         int index;
  338.         struct List *list = (struct List *) &s->SelList;
  339.  
  340.         switch (s->SelMsg.Code) {
  341.                 case '\r' :
  342.                         return SELOkClicked(s);
  343.                         break;
  344.                 case VANILLA_ESC :
  345.                         return SELCancelClicked(s);
  346.                         break;
  347.  
  348.                 case VANILLA_DEL :
  349.                         s->SelCompleteBuf[1] = '\0';
  350.                 case '\b' :
  351.                         if (len = strlen(s->SelCompleteBuf)) {
  352.                                 s->SelCompleteBuf[len-1] = '\0';
  353.                                 if ((index = IndexInList(list, s->SelCompleteBuf)) >= 0) {
  354.                                         s->SelIndex = index;
  355.                                         UpdateListView(s);
  356.                                 }
  357.                         }
  358.                         SetWindowTitles(s->SelWnd, s->SelWdt ,(UBYTE *)-1);
  359.                         break;
  360.                 case '\t' :
  361.                         if ((index = NextMatch(FindIndex(list, s->SelIndex), s->SelCompleteBuf)) >= 0) {
  362.                                         s->SelIndex += index;
  363.                                         UpdateListView(s);
  364.                                 } else DisplayBeep(Scr);
  365.                         break;
  366.  
  367.                 default :
  368.                         if ((len = strlen(s->SelCompleteBuf)) < COMPLETEBUFSIZ-1 ) {
  369.                                 s->SelCompleteBuf[len] = s->SelMsg.Code;
  370.                                 s->SelCompleteBuf[len+1] = '\0';
  371.                                 if ((index = IndexInList(list, s->SelCompleteBuf)) >= 0) {
  372.                                         s->SelIndex = index;
  373.                                         UpdateListView(s);
  374.                                         SetWindowTitles(s->SelWnd, s->SelWdt ,(UBYTE *)-1);
  375.                                 }
  376.                                 else {
  377.                                         s->SelCompleteBuf[len] = '\0';
  378.                                         DisplayBeep(Scr);
  379.                                 }
  380.                         }
  381.                         break;
  382.         }
  383.         return SEL_SELECT;
  384. }
  385.  
  386. static int SelRawKey(Select *s)
  387. {
  388.         /* routine for "IDCMP_RAWKEY". */
  389.  
  390.         int index;
  391.         struct List *list = (struct List *)&s->SelList;
  392.  
  393.         int rows = (s->ListView->Height-4)/FontY;        /* Rows visible in listview. Ugly but works */
  394.  
  395.         switch (s->SelMsg.Code) {
  396.                 case RAW_UP :
  397.                         if (s->SelIndex == 0) return SEL_PRIVATE;
  398.                         if (s->SelMsg.Qualifier & IXSYM_ALTMASK)
  399.                                 s->SelIndex = 0;
  400.                         else if (s->SelMsg.Qualifier & IXSYM_SHIFTMASK) {
  401.                                 s->SelIndex -= rows-1;
  402.                                 if (s->SelIndex < 0) s->SelIndex = 0;
  403.                         }
  404.                         else s->SelIndex--;
  405.  
  406.                         break;
  407.                 case RAW_DOWN :
  408.                         if (s->SelIndex >= s->SelTotal-1) return SEL_PRIVATE;
  409.                         if (s->SelMsg.Qualifier & IXSYM_ALTMASK)
  410.                                  s->SelIndex = s->SelTotal - 1;
  411.                         else if (s->SelMsg.Qualifier & IXSYM_SHIFTMASK) {
  412.                                 s->SelIndex += rows-1;
  413.                                 if (s->SelIndex > s->SelTotal-1) s->SelIndex = s->SelTotal - 1;
  414.                         }
  415.                         else s->SelIndex++;
  416.                         break;
  417.                 case RAW_TAB :
  418.                         if ((index = PrevMatch(FindIndex(list, s->SelIndex), s->SelCompleteBuf)) >= 0) {
  419.                                         s->SelIndex -= index;
  420.                                         UpdateListView(s);
  421.                                 } else DisplayBeep(Scr);
  422.                         break;
  423.                 case RAW_HELP :
  424.                         return SEL_HELP;
  425.                         break;
  426.                 default :
  427.                         return SEL_PRIVATE;
  428.         }
  429.  
  430.         UpdateListView(s);
  431.         return SEL_SELECT;
  432. }
  433.  
  434.  
  435. /**********************************************************************/
  436. /*                        Interface functions                         */
  437. /**********************************************************************/
  438.  
  439. BOOL FixSelectSize(Select *s, int n)
  440. {
  441.         /* Makes the Select object allocate memory for n elements in one chunk for */
  442.         /* all fields. It is illegal to add more fields than allocated after this */
  443.         /* Use RemoveAllFields() to free up everything. */
  444.  
  445.         if (!(s->NodeArray = malloc(n * sizeof(struct Node)))) return FALSE;
  446.         s->FirstFree = 0;
  447.         return TRUE;
  448. }
  449.  
  450. char *SelectedString(Select *s)
  451. {
  452. /* Returns the selected string */
  453.  
  454.         return FindIndex((struct List *)&s->SelList, s->SelIndex)->ln_Name;
  455. }
  456.  
  457. void UpdateString(Select *s, int index, char *newstring)
  458. {
  459. /* Changes a string. */
  460.  
  461.         if (s->SelWnd)
  462.                 GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, ~0, TAG_END); // Detach
  463.  
  464.         FindIndex((struct List *)&s->SelList, index)->ln_Name = newstring;
  465.  
  466.         if (s->SelWnd)
  467.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, &s->SelList, TAG_END);
  468. }
  469.  
  470.  
  471. /* // I comment this to save space
  472. char *AddStringFirst(Select *s, char *str)
  473. {
  474.         struct Node *newnode;
  475.  
  476.         if (s->NodeArray)       newnode = s->NodeArray[s->FirstFree++];
  477.         else if (!(newnode = (struct Node *)malloc(sizeof(struct Node)))) return str;
  478.         newnode->ln_Name = str;
  479.  
  480.         if (s->SelWnd)
  481.                 GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, ~0, TAG_END); // Detach
  482.  
  483.         AddHead((struct List *)&s->SelList, newnode);
  484.         s->SelTotal++;
  485.  
  486.         if (s->SelWnd)
  487.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, &s->SelList, TAG_END);
  488.  
  489.         return str;
  490. }
  491. */
  492. char *AddStringLast(Select *s, char *str)
  493. {
  494.         struct Node *newnode;
  495.  
  496.         if (s->NodeArray)       newnode = &s->NodeArray[s->FirstFree++];
  497.         else if (!(newnode = (struct Node *)malloc(sizeof(struct Node)))) return str;
  498.         newnode->ln_Name = str;
  499.  
  500.         if (s->SelWnd)
  501.                 GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, ~0, TAG_END); // Detach
  502.  
  503.         AddTail((struct List *)&s->SelList, newnode);
  504.         s->SelTotal++;
  505.  
  506.         if (s->SelWnd)
  507.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, &s->SelList, TAG_END);
  508.  
  509.         return str;
  510. }
  511.  
  512. /* // I comment this to save space
  513. char *AddString(Select *s, char *str, int index)
  514. {
  515.         struct Node *newnode;
  516.  
  517.         if (s->NodeArray)       newnode = &s->NodeArray[s->FirstFree++];
  518.         else if (!(newnode = (struct Node *)malloc(sizeof(struct Node)))) return str;
  519.         newnode->ln_Name = str;
  520.  
  521.         if (s->SelWnd)
  522.                 GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, ~0, TAG_END); // Detach
  523.  
  524.         if (index == 0) AddHead((struct List *)&s->SelList, newnode);
  525.         else Insert((struct List *)&s->SelList, newnode,
  526.                                          FindIndex((struct List *)&s->SelList, index-1));
  527.         s->SelTotal++;
  528.  
  529.         if (s->SelWnd)
  530.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, &s->SelList, TAG_END);
  531.  
  532.         return str;
  533. }
  534.  
  535. char *RemoveFirstString(Select *s)
  536. {
  537.         struct Node *old;
  538.         char *oldstr;
  539.  
  540.         if (!s->SelTotal) return NULL;
  541.  
  542.         if (s->SelWnd)
  543.                 GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, ~0, TAG_END); // Detach
  544.  
  545.         old = RemHead((struct List *)&s->SelList);
  546.         s->SelTotal--;
  547.         if (s->SelIndex == s->SelTotal) s->SelIndex--;
  548.  
  549.         if (s->SelWnd)
  550.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, &s->SelList, TAG_END);
  551.  
  552.         oldstr = old->ln_Name;
  553.         if (!s->NodeArray) free(old);
  554.         return oldstr;
  555. }
  556.  
  557. char *RemoveLastString(Select *s)
  558. {
  559.         struct Node *old;
  560.         char *oldstr;
  561.  
  562.         if (!s->SelTotal) return NULL;
  563.  
  564.         if (s->SelWnd)
  565.                 GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, ~0, TAG_END); // Detach
  566.  
  567.         old = RemTail((struct List *)&s->SelList);
  568.  
  569.         s->SelTotal--;
  570.         if (s->SelIndex == s->SelTotal) s->SelIndex--;
  571.  
  572.         if (s->SelWnd)
  573.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, &s->SelList, TAG_END);
  574.  
  575.         oldstr = old->ln_Name;
  576.         if (!s->NodeArray) free(old);
  577.         return oldstr;
  578. }
  579.  
  580. char *RemoveString(Select *s, int index)
  581. {
  582.         struct Node *old;
  583.         char *oldstr;
  584.  
  585.         if (s->SelWnd)
  586.                 GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, ~0, TAG_END); // Detach
  587.  
  588.         old = FindIndex((struct List *)&s->SelList, index);
  589.         Remove(old);
  590.         s->SelTotal--;
  591.         if (s->SelIndex == s->SelTotal) s->SelIndex--;
  592.  
  593.         if (s->SelWnd)
  594.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, &s->SelList, TAG_END);
  595.  
  596.         if (old) {
  597.                 oldstr = old->ln_Name;
  598.                 if (!s->NodeArray) free(old);
  599.                 return oldstr;
  600.         }
  601.         return NULL;
  602. }
  603.  
  604. */
  605.  
  606. void RemoveAllStrings(Select *s)
  607. {
  608.         struct Node *old;
  609.  
  610.         if (s->SelWnd)
  611.                 GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, ~0, TAG_END); // Detach
  612.  
  613.         if (s->NodeArray) {
  614.                 free(s->NodeArray);
  615.                 s->NodeArray = NULL;
  616.                 NewList((struct List *)&s->SelList);
  617.         }
  618.         else while (old = RemTail((struct List *)&s->SelList)) free(old);
  619.  
  620.         if (s->SelWnd)
  621.         GT_SetGadgetAttrs(s->ListView, s->SelWnd, NULL, GTLV_Labels, &s->SelList, TAG_END);
  622.         s->SelTotal = 0;
  623. }
  624.  
  625. void DisableSelect(Select *s, BOOL flag) {
  626.                 if (s->SelWnd) {
  627.                         GT_SetGadgetAttrs(s->ListView,s->SelWnd,NULL,
  628.                          GA_Disabled, flag, TAG_DONE);
  629.                 }
  630. }
  631.  
  632. void CurrentIndex(Select *s, int index)
  633. {
  634.         if (s) {
  635.                 s->SelIndex = index;
  636.                 if (s->SelWnd) UpdateListView(s);
  637.         }
  638. }
  639.  
  640. int HandleSelectIDCMP(Select *s)
  641. {
  642.         struct IntuiMessage     *m;
  643.         int                     (*func)(Select*);
  644.         BOOL                    running = SEL_PRIVATE;
  645.  
  646.         while( s->SelWnd && (m = GT_GetIMsg( s->SelWnd->UserPort ))) {
  647.  
  648.                 CopyMem(( char * )m, ( char * )&s->SelMsg, (long)sizeof( struct IntuiMessage ));
  649.  
  650.                 GT_ReplyIMsg( m );
  651.  
  652.                 switch ( s->SelMsg.Class ) {
  653.  
  654.                         case    IDCMP_REFRESHWINDOW:
  655.                                 GT_BeginRefresh( s->SelWnd );
  656.                                 GT_EndRefresh( s->SelWnd, TRUE );
  657.                                 break;
  658.  
  659.                         case    IDCMP_CLOSEWINDOW:
  660.                                 running = SelCloseWindow(s);
  661.                                 break;
  662.  
  663.                         case    IDCMP_NEWSIZE:
  664.                                 running = SelNewSize(s);
  665.                                 break;
  666.  
  667.                         case    IDCMP_VANILLAKEY:
  668.                                 running = SelVanillaKey(s);
  669.                                 break;
  670.  
  671.                         case    IDCMP_RAWKEY:
  672.                                 running = SelRawKey(s);
  673.                                 break;
  674.  
  675.                         case    IDCMP_GADGETUP:
  676.                         case    IDCMP_GADGETDOWN:
  677.                                 func = (int(*)(Select*))(( struct Gadget * )s->SelMsg.IAddress )->UserData;
  678.                                 if(func)
  679.                                     running = func(s);
  680.                                 break;
  681.                 }
  682.         }
  683.         return( running );
  684. }
  685.  
  686. int OpenSelect(Select *s, struct Window *parentwin, char *wintitle, char *screentitle)
  687. {
  688.         char *bufp, *namep;
  689.  
  690.         if (s->SelWnd) return 5L; /* Already opened */
  691.  
  692.         if (s->SelWidth == ~0) {        /* Window has never been opened before */
  693.                 s->SelWidth = 220;
  694. //              ComputeFont( s->SelWidth, s->SelHeight );
  695.                 s->SelWidth = ComputeX( s->SelWidth );
  696.                 s->SelHeight = ComputeY( s->SelHeight );
  697.         
  698.                 if (parentwin) {
  699.                         s->SelLeft =  parentwin->LeftEdge + parentwin->Width;
  700.                         s->SelTop = parentwin->TopEdge + (parentwin->Height - s->SelHeight)/2;
  701.                 }
  702.                 if (s->SelLeft + s->SelWidth > Scr->Width)
  703.                         s->SelLeft = parentwin->LeftEdge - s->SelWidth;
  704.         }
  705.  
  706.         /* Strip underscore _ for cosmethic reasons */
  707.         for (bufp = s->SelWdt, namep = wintitle; *namep; namep++)
  708.                 if (*namep != '_') *bufp++ = *namep;
  709.         
  710.     /* Strip trailing ':' if there's any */
  711.         if(*(bufp-1) != ':')
  712.                 *bufp = ':';
  713.         else
  714.                 *bufp = '\0';
  715.  
  716.         s->SelCompleteBuf = bufp+1;
  717.         s->SelCompleteBuf[0] = '\0';
  718.  
  719.         s->SelZoom[0] = s->SelLeft;
  720.         s->SelZoom[1] = 0;
  721.         s->SelZoom[2] = s->SelWidth;
  722.         s->SelZoom[3] = Scr->Height;
  723.         
  724.         if ( ! ( s->SelWnd = OpenWindowTags( NULL,
  725.                                 WA_Left,        s->SelLeft,
  726.                                 WA_Top,         s->SelTop,
  727.                                 WA_Width,       s->SelWidth,
  728.                                 WA_Height,      s->SelHeight,
  729.                                 WA_IDCMP,       LISTVIEWIDCMP|BUTTONIDCMP|IDCMP_NEWSIZE|IDCMP_CLOSEWINDOW|IDCMP_RAWKEY|IDCMP_VANILLAKEY|IDCMP_REFRESHWINDOW,
  730.                                 WA_Flags,       WFLG_SIZEGADGET|WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_SIZEBBOTTOM|WFLG_SIMPLE_REFRESH|WFLG_ACTIVATE|WFLG_RMBTRAP,
  731.                                 WA_Title,       s->SelWdt,
  732.                                 WA_ScreenTitle, screentitle,
  733.                                 WA_PubScreen,   Scr,
  734.                                 WA_MinWidth,    160,
  735.                                 WA_MinHeight,   120,
  736.                                 WA_MaxWidth,    -1,
  737.                                 WA_MaxHeight,   -1,
  738.                                 WA_Zoom, s->SelZoom,
  739.                                 TAG_DONE )))
  740.         return( 4L );
  741.  
  742.         MyCreateAllGadgets(s);
  743.         return( 0L );
  744. }
  745.  
  746. void CloseSelect(Select *s)
  747. {
  748.         if ( s->SelWnd        ) {
  749.                 s->SelLeft = s->SelWnd->LeftEdge;
  750.                 s->SelTop = s->SelWnd->TopEdge;
  751.                 s->SelWidth = s->SelWnd->Width;
  752.                 s->SelHeight = s->SelWnd->Height;
  753.  
  754.                 CloseWindow( s->SelWnd );
  755.                 s->SelWnd = NULL;
  756.         }
  757.  
  758.         if ( s->SelGList      ) {
  759.                 FreeGadgets( s->SelGList );
  760.                 s->SelGList = NULL;
  761.         }
  762. }
  763.  
  764. Select *NewSelect(void)
  765. {
  766. /* Data för ListView gadget */
  767.         Select *s = (Select*) malloc(sizeof(Select));
  768.         if (!s) return NULL;
  769.  
  770.         s->SelWnd = NULL;
  771.         s->SelGList = NULL;
  772.         s->ListView = NULL;
  773.         s->SelWidth = ~0; /* (220) Window has never been opened before */
  774.         s->SelHeight = 280;
  775.         s->SelLeft =  (Scr->Width - 220) >> 1;
  776.         s->SelTop = (Scr->Height - s->SelHeight) >> 1;
  777.         s->SelIndex = 0;
  778.         s->SelTotal = 0;
  779.         s->StartSecs = 0, s->StartMicros = 0;
  780.         s->NodeArray = NULL;
  781.  
  782.         NewList((struct List *)&s->SelList);
  783.  
  784.         return s;
  785. }
  786.  
  787. void DeleteSelect(Select *s)
  788. {
  789.         CloseSelect(s);
  790.         RemoveAllStrings(s);
  791.         free(s);
  792. }
  793.